package custom.base.utils.notification;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.SystemClock;
import android.widget.RemoteViews;

import androidx.core.app.NotificationCompat;

import java.util.HashMap;

import custom.base.utils.TxtUtil;

import static android.content.Context.NOTIFICATION_SERVICE;

/**
 * Created by luozi on 2016/11/18.
 */

public class NotificationUtils implements NotifiyID {
    private volatile static NotificationUtils instance;
    private Context context;
    /**
     * Notification管理
     */
    private NotificationManager mNotificationManager;
    /**
     * id索引用作自动生成通知栏id用
     */
    private int indexID = 0;
    /**
     * 映射id
     */
    HashMap<String, Integer> mapID = new HashMap<>();

    /**
     * 通知列表管理器
     */
    private HashMap<Integer, NotificationBean> notificationHashMap = new HashMap<>();

    private NotificationUtils(Context context) {
        this.context = context;
        mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
        indexID = Integer.MAX_VALUE;
    }

    /**
     * 单例模式
     */
    public static NotificationUtils getInstance(Context context) {
        synchronized (NotificationUtils.class) {
            if (instance == null) instance = new NotificationUtils(context);
            return instance;
        }

    }

    /**
     * 生成一个正常的通知,不带动作行为的通知
     * * @param tvTitle         标题
     *
     * @param content  内容文本
     * @param ticker   通知闪烁文本
     * @param icon     通知图标
     * @param notifyId 通知id编号
     * @param title    通知标题     * @param isNotify   是否显示通知
     */
    public void showNormalNotification(int notifyId, String title, String content, String ticker, int icon, boolean isNotify, int progress) {
        createDefaultNotification(null, notifyId, title, content, ticker, 0, Notification.PRIORITY_DEFAULT, true, false,
                Notification.DEFAULT_VIBRATE, icon, null, null, isNotify, progress);
    }

    /**
     * 生成一个带行为动作得到通知
     * * @param tvTitle         标题
     *
     * @param content  内容文本
     * @param ticker   通知闪烁文本
     * @param icon     通知图标
     * @param intent   动作意图
     * @param notifyId 通知id编号
     * @param title    通知标题     * @param isNotify   是否显示通知
     */
    public void showIntentNotification(int notifyId, String title,
                                       String content, String ticker, int icon, Intent intent, Intent deleteIntent, boolean isNotify, int progress) {
        createDefaultNotification(null, notifyId, title, content, ticker, 0, Notification.PRIORITY_DEFAULT, true, false,
                Notification.DEFAULT_VIBRATE, icon, intent, deleteIntent, isNotify, progress);
    }

    /**
     * 生成一个自定义view 的通知,不带动作意图
     * * @param tvTitle         标题
     *
     * @param content  内容文本
     * @param ticker   通知闪烁文本
     * @param icon     通知图标
     * @param notifyId 通知id编号
     * @param title    通知标题
     * @param views    自定义view     * @param isNotify   是否显示通知
     */
    public void showCustomViewNotification(RemoteViews views, int notifyId,
                                           String title, String content, String ticker, int icon, boolean isNotify, int progress) {
        createDefaultNotification(views, notifyId, title, content, ticker, 0, Notification.PRIORITY_DEFAULT, true, false,
                Notification.DEFAULT_VIBRATE, icon, null, null, isNotify, progress);
    }

    /**
     * 生成一个自定义view 带动作意图的通知
     * * @param tvTitle         标题
     *
     * @param content  内容文本
     * @param ticker   通知闪烁文本
     * @param icon     通知图标
     * @param notifyId 通知id编号
     * @param title    通知标题
     * @param views    自定义view     * @param isNotify   是否显示通知
     */
    public void showCustomViewNotification(RemoteViews views, int notifyId,
                                           String title, String content, String ticker, int icon, Intent intent, Intent deleteIntent, boolean isNotify, int progress) {
        createDefaultNotification(views, notifyId, title, content, ticker, 0, Notification.PRIORITY_DEFAULT, true, false,
                Notification.DEFAULT_VIBRATE, icon, intent, deleteIntent, isNotify, progress);
    }


    /**
     * 创建和展示一个通知栏
     *
     * @param title       标题
     * @param content     内容文本
     * @param ticker      通知闪烁文本
     * @param number      通知数量
     * @param pri         通知优先级
     * @param autoCancel  是否可以自动取消
     * @param ongoing     设置他为一个正在进行的通知，当设置后通知栏为常驻通知栏。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐
     *                    )或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
     * @param defaults    向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置，使用defaults属性，
     *                    //设置系统默认提醒效果，一旦设置默认提醒效果，则自定义的提醒效果会全部失效。具体可看源码
     *                    //添加默认震动效果,需要申请震动权限
     *                    //<uses-permission android:name="android.permission.VIBRATE" />
     *                    Notification.DEFAULT_VIBRATE
     *                    //添加系统默认声音效果，设置此值后，调用setSound()设置自定义声音无效
     *                    Notification.DEFAULT_SOUND
     *                    //添加默认呼吸灯效果，使用时须与 Notification.FLAG_SHOW_LIGHTS 结合使用，否则无效
     *                    Notification.DEFAULT_LIGHTS
     *                    //添加上述三种默认提醒效果
     *                    Notification.DEFAULT_ALL
     *                    //提醒效果常用 Flag
     *                    //三色灯提醒，在使用三色灯提醒时候必须加该标志符
     *                    Notification.FLAG_SHOW_LIGHTS
     *                    //发起正在运行事件（活动中）
     *                    Notification.FLAG_ONGOING_EVENT
     *                    //让声音、振动无限循环，直到用户响应 （取消或者打开）
     *                    Notification.FLAG_INSISTENT
     *                    //发起Notification后，铃声和震动均只执行一次
     *                    Notification.FLAG_ONLY_ALERT_ONCE
     *                    //用户单击通知后自动消失
     *                    Notification.FLAG_AUTO_CANCEL
     *                    //只有调用NotificationManager.cancel()时才会清除
     *                    Notification.FLAG_NO_CLEAR
     *                    //表示正在运行的服务
     *                    Notification.FLAG_FOREGROUND_SERVICE
     * @param clickIntent 意图，动作可以添加行为动作：开启activity、打开某个文件等等
     * @param icon        通知图标
     * @param isNotify    是否显示通知
     */
    public Notification createDefaultNotification(RemoteViews views, int notifyId, String title, String content, String ticker, int number,
                                                  int pri, boolean autoCancel, boolean ongoing, int defaults, int icon,
                                                  Intent clickIntent, Intent deleteIntent, boolean isNotify, int progress) {
        /**
         * Notification构造器
         */
        NotificationCompat.Builder mBuilder;
        /**如果存在就从历史builder里面取*/
        if (Build.VERSION.SDK_INT >= 26) {//android O以上
            NotificationChannel channel = new NotificationChannel("1000", "default", NotificationManager.IMPORTANCE_DEFAULT);
            channel.enableLights(false); //是否在桌面icon右上角展示小红点
            channel.setLightColor(Color.RED); //小红点颜色
            channel.setShowBadge(false); //是否在久按桌面图标时显示此渠道的通知
            channel.enableVibration(false);
            channel.setSound(null, null);
            channel.setVibrationPattern(new long[]{0L, 0L, 0L, 0L});
            mNotificationManager.createNotificationChannel(channel);

            mBuilder = new NotificationCompat.Builder(context, channel.getId());
        } else {
            mBuilder = new NotificationCompat.Builder(context, title);
        }

        if (views != null)
            mBuilder.setContent(views);
        if (defaults >= 0)
            mBuilder.setDefaults(defaults);//向通知添加声音、闪灯和振动效果的最简单、最一致的方式是使用当前的用户默认设置，使用defaults属性，可以组合：
        mBuilder.setContentTitle(title)
                .setContentText(content)
                .setSound(null)
                .setTicker(ticker)//通知首次出现在通知栏，带上升动画效果的
                .setWhen(System.currentTimeMillis())//通知产生的时间，会在通知信息里显示
                .setPriority(pri)//设置该通知优先级
                .setLights(Color.GREEN, Color.GREEN, Color.GREEN)
                .setVibrate(new long[]{0L, 0L, 0L, 0L})//取消震动
                .setAutoCancel(autoCancel)//设置这个标志当用户单击面板就可以让通知将自动取消
                .setOngoing(ongoing)//ture，设置他为一个正在进行的通知。他们通常是用来表示一个后台任务,用户积极参与(如播放音乐)或以某种方式正在等待,因此占用设备(如一个文件下载,同步操作,主动网络连接)
                .setSmallIcon(icon);

        if (number >= 0)
            mBuilder.setNumber(number);//显示数量
        if (clickIntent != null)
            mBuilder.setContentIntent(getDefalutIntent(context, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT));
        if (deleteIntent != null)
            mBuilder.setDeleteIntent(getDefalutIntent(context, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT));

        if (progress >= 0)
            mBuilder.setProgress(100, progress, false);

        NotificationBean bean = new NotificationBean();
        bean.setNotificationID(notifyId);
        bean.setBuilder(mBuilder);
        notificationHashMap.put(notifyId, bean);

        return notify(notifyId);
    }

    /**
     * 根据notifyid设置进度,100为最大
     */
    public NotificationUtils setProgress(int notifyID, int progress) {
        NotificationBean bean = notificationHashMap.get(notifyID);
        if (bean == null)
            return this;
        bean.getBuilder().setProgress(100, progress, false);
        return this;
    }

    /**
     * 根据notifyid设置标题
     */
    public NotificationUtils setTitle(int notifyID, String title) {
        NotificationBean bean = notificationHashMap.get(notifyID);
        if (bean == null)
            return this;
        bean.getBuilder().setContentTitle(title);
        return this;
    }

    /**
     * 根据notifyid设置内容
     */
    public NotificationUtils setContent(int notifyID, String content) {
        NotificationBean bean = notificationHashMap.get(notifyID);
        if (bean == null)
            return this;
        bean.getBuilder().setContentText(content);
        return this;
    }

    /**
     * 根据notifyid设置时间
     */
    public NotificationUtils setWhen(int notifyID, long time) {
        NotificationBean bean = notificationHashMap.get(notifyID);
        if (bean == null)
            return this;
        bean.getBuilder().setWhen(time);
        return this;
    }

    /**
     * 展示对应的通知
     */
    public Notification notify(int notifyID) {
        NotificationBean bean = notificationHashMap.get(notifyID);
        if (bean == null)
            return null;
        Notification notification = bean.getBuilder().build();
        mNotificationManager.notify(bean.getNotificationID(), notification);
        return notification;
    }

    /**
     * 展示所有通知(特殊情况下使用)
     */
    public void showAllNotifications() {
        for (int i = 0; i < notificationHashMap.size(); i++) {
            NotificationBean bean = (NotificationBean) notificationHashMap.values().toArray()[i];
            if (mNotificationManager != null)
                mNotificationManager.notify(bean.getNotificationID(), bean.getBuilder().build());
        }
    }

    /**
     * 移除通知
     */
    public void removeNotification(int notifyId) {
        notificationHashMap.remove(notifyId);
        if (mNotificationManager != null)
            mNotificationManager.cancel(notifyId);//删除一个特定的通知ID对应的通知
    }

    /**
     * 移除通知
     */
    public void removeAllNotification() {
        notificationHashMap.clear();
        if (mNotificationManager != null)
            mNotificationManager.cancelAll();
    }

    /**
     * 得到不同重复映射的通知id，当传入的string相同时取出的id也相同，不同则不同
     */
    public int getNoRepeatMapID(String map) {
        if (TxtUtil.isEmpty(map))
            return 0;
        if (mapID.containsKey(map)) {
            return mapID.get(map);
        } else {
            int tmp = Integer.MAX_VALUE - indexID++;
            mapID.put(map, tmp);
            return tmp;
        }
    }

    /**
     * 获取默认的pendingIntent,为了防止2.3及以下版本报错
     *
     * @param context
     * @param intent  行为动作意图，如果为空的话将会自动生成一个空intent
     * @param flags   动作标记 点击去除：Notification.FLAG_AUTO_CANCEL，在顶部常驻:Notification.FLAG_ONGOING_EVENT
     */
    public PendingIntent getDefalutIntent(Context context, Intent intent, int flags) {
        //可以添加intent的启动路径
//        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
//        stackBuilder.addParentStack(NotifyRegularActivity.class);
//        stackBuilder.addNextIntent(notifyIntent);

        PendingIntent pendingIntent = PendingIntent.getActivity(context, (int) SystemClock.uptimeMillis(),
                intent == null ? new Intent() : intent, flags);

        return pendingIntent;
    }
}
